package com.yuxl.admin.common.socket.service;

import com.yuxl.admin.common.security.service.JwtService;
import com.yuxl.admin.common.security.service.RedisTokenService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.socket.WebSocketSession;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Service
public class WebSocketService {

    // 使用ConcurrentHashMap存储WebSocket会话，键为用户名，值为WebSocketSession列表
    private final Map<String, List<WebSocketSession>> sessions = new ConcurrentHashMap<>();

    @Resource
    private RedisTokenService redisTokenService;
    @Resource
    private JwtService jwtService;

    /**
     * 添加新的WebSocket会话
     * @param username 用户名
     * @param session WebSocket会话
     */
    public void addSession(String username, WebSocketSession session) {
        sessions.computeIfAbsent(username, k -> new ArrayList<>()).add(session);
        log.debug("用户 {} 的新WebSocket会话已添加", username);
    }

    /**
     * 获取指定用户的所有WebSocket会话
     * @param username 用户名
     * @return 用户的WebSocket会话列表
     */
    public List<WebSocketSession> getSessions(String username) {
        List<WebSocketSession> userSessions = sessions.get(username);
        if (userSessions != null && !userSessions.isEmpty()) {
            log.debug("获取到用户 {} 的 {} 个WebSocket会话", username, userSessions.size());
        } else {
            log.debug("未找到用户 {} 的WebSocket会话", username);
        }
        return userSessions != null ? userSessions : new ArrayList<>();
    }

    /**
     * 移除指定用户的WebSocket会话
     * @param username 用户名
     * @param session 要移除的会话
     */
    public void removeSession(String username, WebSocketSession session) {
        List<WebSocketSession> userSessions = sessions.get(username);
        if (userSessions != null) {
            userSessions.remove(session);
            if (userSessions.isEmpty()) {
                sessions.remove(username);
            }
            log.debug("用户 {} 的一个WebSocket会话已移除", username);
        }
    }

    /**
     * 获取所有WebSocket会话
     * @return 所有WebSocket会话的Map
     */
    public Map<String, List<WebSocketSession>> getAllSessions() {
        log.debug("获取所有WebSocket会话，当前用户数: {}", sessions.size());
        return sessions;
    }

    /**
     * 获取WebSocket会话中的用户名
     * @param session WebSocket会话
     * @return 用户名
     */
    public String getUsername(WebSocketSession session) {
        return (String) session.getAttributes().get("username");
    }

    /**
     * 获取WebSocket会话中的token
     * @param session WebSocket会话
     * @return token
     */
    public String getToken(WebSocketSession session) {
        return (String) session.getAttributes().get("token");
    }

    /**
     * 检查WebSocket会话中的用户是否已登录
     * @param session WebSocket会话
     * @return 用户是否已登录的Mono<Boolean>
     */
    public Mono<Boolean> isUserLoggedIn(WebSocketSession session) {
        String username = getUsername(session);
        String token = getToken(session);
        return isUserLoggedIn(username, token);
    }

    /**
     * 检查用户是否已登录
     * @param username 用户名
     * @param token JWT令牌
     * @return 用户是否已登录的Mono<Boolean>
     */
    public Mono<Boolean> isUserLoggedIn(String username, String token) {
        log.debug("检查用户 {} 的登录状态", username);
        return redisTokenService.getToken(username)
                .flatMap(storedToken -> {
                    if (storedToken != null && storedToken.equals(token)) {
                        // 如果Redis中存储的令牌与提供的令牌匹配，则验证JWT
                        log.debug("用户 {} 的令牌在Redis中存在，正在验证JWT", username);
                        return jwtService.validateToken(token, username);
                    }
                    log.debug("用户 {} 的令牌在Redis中不存在或不匹配", username);
                    return Mono.just(false);
                })
                .defaultIfEmpty(false)
                .doOnNext(isLoggedIn -> log.debug("用户 {} 的登录状态: {}", username, isLoggedIn ? "已登录" : "未登录"));
    }

    /**
     * 验证WebSocket连接
     * @param username 用户名
     * @param token JWT令牌
     * @return 连接是否有效的Mono<Boolean>
     */
    public Mono<Boolean> validateConnection(String username, String token) {
        log.debug("验证WebSocket连接: 用户名 = {}, 令牌 = {}", username, token);
        return isUserLoggedIn(username, token)
                .doOnNext(isValid -> log.debug("WebSocket连接验证结果: {}", isValid ? "有效" : "无效"));
    }

    /**
     * 关闭WebSocket连接
     * @param username 用户名
     * @return 表示操作完成的Mono<Void>
     */
    public Mono<Void> closeConnection(String username) {
        return Mono.fromRunnable(() -> {
            List<WebSocketSession> userSessions = sessions.remove(username);
            if (userSessions != null) {
                userSessions.forEach(session -> {
                    if (session.isOpen()) {
                        session.close().subscribe();
                    }
                });
                log.debug("用户 {} 的所有WebSocket连接已关闭", username);
            } else {
                log.debug("未找到用户 {} 的WebSocket连接", username);
            }
        });
    }

}